﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTO;
using DAL;

namespace BLL.Store
{
    public class Product:BaseStore
    {
        #region "Constructors"
        public Product(int productID, DateTime addedDate, string addedBy, int departmentID, string title, string codeProduct, string orgin, string sKU, decimal unitPrice, string description, int discountPercentage, int unitsInStock, int votes, int totalRating, int quantity, bool isshow, bool isnew, int pictureId)
		{
            this.ID = productID;
            this.AddedDate = addedDate;
            this.AddedBy = addedBy;
            this.DepartmentID = departmentID;
            this.Title = title;
            this.CodeProduct = codeProduct;
            this.Orgin = orgin;
            this.SKU = sKU;
            this.UnitPrice = unitPrice;
            this.Description = description;
            this.DiscountPercentage = discountPercentage;
            this.UnitsInStock = unitsInStock;
            this.Votes = votes;
            this.TotalRating = totalRating;
            this.Quantity = quantity;
            this.IsShow = isshow;
            this.IsNew = isnew;
            this.PictureId = pictureId;
        }
		#endregion
		
		#region "Public Properties"
        
        public int DepartmentID { get; set; }

        public string Title { get; set; }

        public string CodeProduct { get; set; }

        public string Orgin { get; set; }

        public string SKU { get; set; }

        public decimal UnitPrice { get; set; }

        public string Description { get; set; }

        public int DiscountPercentage { get; set; }

        public int UnitsInStock { get; set; }

        public int Votes { get; set; }

        public int TotalRating { get; set; }

        public int Quantity { get; set; }

        public bool IsShow { get; set; }

        public bool IsNew { get; set; }

        public int PictureId { get; set; }
        
        public decimal FinalUnitPrice
        {
            get
            {
                if (this.DiscountPercentage > 0)
                    if (this.UnitPrice > 0)
                        return 100 - Math.Round(((this.DiscountPercentage / this.UnitPrice) * 100), 0);
                    else
                        return 0;
                else
                    return this.UnitPrice;
            }
        }

        public string StringUnitPrice
        {
            get { return UnitPrice.ToString("#0,000") + " VND"; }
        }

        public string StringFinalUnitPrice
        {
            get { return FinalUnitPrice.ToString("#0,000") + " VND"; }
        }

        public string StringDiscountPercentage
        {
            get { return DiscountPercentage.ToString("#0,000") + " VND"; }
        }

        public string RoundUnitPrice
        {
            get { return Math.Round((this.UnitPrice), 0).ToString(); }
        }

        public Store.Department Department
        {
            get { return Store.Department.GetDepartmentByID(this.DepartmentID); }
        }

        public bool IsNews
        {
            get
            {
                double distance = (DateTime.Now.Subtract(AddedDate)).TotalDays;
                return (distance <= 30);
            }

        }

        public bool IsHot
        {
            get
            {
                return (Quantity <= (double)Globals.Settings.Store.NProductisHot);
            }

        }

		#endregion

        #region Get From ProductDetail
        private static Product GetProductFromProductDetails(ProductDetails record)
        {
            if (record == null)
                return null;
            else
            {
                return new Product(record.ID, record.AddedDate, record.AddedBy, record.DepartmentID, record.Title, record.CodeProduct, record.Orgin, record.SKU, record.UnitPrice, record.Description, record.DiscountPercentage, record.UnitsInStock, 
                   record.Votes, record.TotalRating,record.Quantity, record.IsShow,record.IsNew,record.PictureId);
            }
        }

        private static List<Product> GetProductListFromProductDetailsList(List<ProductDetails> recordset)
        {
            List<Product> products = new List<Product>();
            foreach (ProductDetails record in recordset)
                products.Add(GetProductFromProductDetails(record));
            return products;
        }
        #endregion

        #region Static Method
        public static List<Product> ListProducts(int maximumRows, int startRowIndex, string sortExpression)
        {
            List<Product> products = null;
            string key = "Products_" + startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                if (string.IsNullOrEmpty(sortExpression))
                    sortExpression = "";
                List<ProductDetails> recordset = SiteProvider.Store.GetProducts(sortExpression, GetPageIndex(startRowIndex, maximumRows), maximumRows);
                products = GetProductListFromProductDetailsList(recordset);
                BaseStore.CacheData(key, products);
            }
            return products;
        }

        public static List<Product> ListProducts(int departmentID)
        {
            return ListProducts(departmentID, BizObject.MAXROWS, 0, "");
        }

        public static List<Product> ListProducts(int departmentID, int maximumRows, int startRowIndex, string sortExpression)
        {
            if (departmentID == 0)
                return ListProducts(maximumRows, startRowIndex, sortExpression);

            List<Product> products = null;
            string key = "Products_ForAll_" + departmentID.ToString() + "_" +
               startRowIndex.ToString() + "_" + maximumRows.ToString() + "_" + sortExpression;

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                //List<ProductDetails> recordset = SiteProvider.Store.ListProductForAll(departmentID, maximumRows, GetPageIndex(startRowIndex, maximumRows), sortExpression);
                List<ProductDetails> recordset = SiteProvider.Store.GetProducts(departmentID, sortExpression, GetPageIndex(startRowIndex, maximumRows), maximumRows);
                products = GetProductListFromProductDetailsList(recordset);
                BaseStore.CacheData(key, products);
            }
            return products;
        }

        public static int GetProductCount()
        {
            int productCount = 0;
            string key = "Products_ProductCount";

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                productCount = (int)BizObject.Cache[key];
            }
            else
            {
                productCount = SiteProvider.Store.GetProductCount();
                BaseStore.CacheData(key, productCount);
            }
            return productCount;
        }

        public static int GetProductCountDepartment(int departmentID)
        {
            if (departmentID <= 0)
                return GetProductCount();

            int productCount = 0;
            string key = "Products_ProductCount_Department_" + departmentID.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                productCount = (int)BizObject.Cache[key];
            }
            else
            {
                productCount = SiteProvider.Store.GetProductCountByDepartment(departmentID);
                BaseStore.CacheData(key, productCount);
            }
            return productCount;
        }

        public static Product GetProductByID(int productID)
        {
            Product product = null;
            string key = "Products_" + productID.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                product = (Product)BizObject.Cache[key];
            }
            else
            {
                product = GetProductFromProductDetails(SiteProvider.Store.GetProductByID(productID));
                BaseStore.CacheData(key, product);
            }
            return product;
        }

        public static List<Product> GetProductIsShow(bool isshow)
        {
            List<Product> product = null;
            string key = "ProductsGetIsShow_" + isshow.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                product = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                product = GetProductListFromProductDetailsList(SiteProvider.Store.GetProductIsShow(isshow));
                BaseStore.CacheData(key, product);
            }
            return product;
        }

        public static List<Product> GetProductIsNew(bool isnew)
        {
            List<Product> product = null;
            string key = "ProductsGetIsNew_" + isnew.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                product = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                product = GetProductListFromProductDetailsList(SiteProvider.Store.GetProductIsNew(isnew));
                BaseStore.CacheData(key, product);
            }
            return product;
        }

        public static bool UpdateProduct(int id, int departmentID, 
            string title, string codeProduct, string orgin, decimal unitPrice, string description,
            int discountPercentage, int quantity, bool isshow, bool isnew, int pictureId)
        {
            codeProduct = BizObject.ConvertNullToEmptyString(codeProduct);
            orgin = BizObject.ConvertNullToEmptyString(orgin);
            title = BizObject.ConvertNullToEmptyString(title);
            description = BizObject.ConvertNullToEmptyString(description);         
            ProductDetails record = new ProductDetails(id, DateTime.Now, "", departmentID, title, codeProduct, orgin, "", unitPrice,
                description, discountPercentage, 0, 0, 0, quantity, isshow, isnew, pictureId);
            bool ret = SiteProvider.Store.UpdateProduct(record);

            BizObject.PurgeCacheItems("Products");
            return ret;
        }

        public static bool DeleteProduct(int id)
        {
            bool ret = SiteProvider.Store.DeleteProduct(id);
            //new RecordDeletedEvent("product", id, null).Raise();
            BizObject.PurgeCacheItems("Products");
            return ret;
        }

        public static int InsertProduct(int departmentID, string title, string codeProduct, string orgin, decimal unitPrice, string description,
            int discountPercentage, int quantity, bool isshow, bool isnew, int pictureId)
        {
            codeProduct = BizObject.ConvertNullToEmptyString(codeProduct);
            orgin = BizObject.ConvertNullToEmptyString(orgin);
            title = BizObject.ConvertNullToEmptyString(title);
            description = BizObject.ConvertNullToEmptyString(description);

            ProductDetails record = new ProductDetails(0, DateTime.Now, BizObject.CurrentUserName, departmentID, title, codeProduct, 
                orgin, "", unitPrice, description, discountPercentage, 0,  0, 0, quantity, isshow, isnew, pictureId);
              
            int tet = SiteProvider.Store.InsertProduct(record);
            BizObject.PurgeCacheItems("Products");
            return tet;
        }

        public static bool RateProduct(int id, int rating)
        {
            return SiteProvider.Store.RateProduct(id, rating);
        }

        public static bool DecrementProductUnitsInStock(int id, int quantity)
        {
            bool ret = SiteProvider.Store.DecrementProductUnitsInStock(id, quantity);
            BizObject.PurgeCacheItems("Product_" + id.ToString());
            return ret;
        }

        public static List<Product> ListProductByDepartemntNoIndex(int departmnetID)
        {
            List<Product> products = null;
            string key = "Products_DepartmentNoIndex_" + departmnetID.ToString(); 

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                List<ProductDetails> recordset = SiteProvider.Store.ListProductByDepartmentNoPageIndex(departmnetID);
                products = GetProductListFromProductDetailsList(recordset);
                BaseStore.CacheData(key, products);
            }
            return products;
        }

        //added by vutdl 22/08/2011
        public static List<Product> ListProduct_ByDepartmentID_NoPageIndex(int departmnetID)
        {
            List<Product> products = null;
            string key = "Products_ByDepartmentID_NoPageIndex_" + departmnetID.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                List<ProductDetails> recordset = SiteProvider.Store.ListProduct_ByDepartmentID_NoPageIndex(departmnetID);
                products = GetProductListFromProductDetailsList(recordset);
                BaseStore.CacheData(key, products);
            }
            return products;
        }
       
        public static List<Product> ListBestProduct()
        {
            return ListProducts(3, 0, "Quantity DESC");
        }

        public static List<Product> ListNewProduct()
        {
            return ListProducts(3, 0, "AddedDate DESC");
        }

        public static List<Product> ListNewProduct(int number)
        {
            return ListProducts(number, 0, "AddedDate DESC");
        }

        public static List<Product> ListProductBySearch(string name, int departmentID, int fromPrice, int endPrice)
        {
            List<Product> products = null;
            string key = "Products_Search_" + name + "_" + departmentID.ToString() + "_" + fromPrice.ToString() + "_" + endPrice.ToString();

            if (BaseStore.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                List<ProductDetails> recordset = SiteProvider.Store.ListProductBySearch(name, departmentID, fromPrice, endPrice);
                products = GetProductListFromProductDetailsList(recordset);
                BaseStore.CacheData(key, products);
            }
            return products;
        }

        public static List<Product> ListProductSameDeparment(int productID)
        {
            Product pro = Product.GetProductByID(productID);
            if (pro == null)
                return ListProductByDepartemntNoIndex(0);
            else
                return ListProductByDepartemntNoIndex(pro.DepartmentID);
        }

        public static bool IncrementProductViewCount(int id)
        {
            return SiteProvider.Store.IncrementProductViewCount(id);
        }

        #endregion

        #region Method

        public bool Delete()
        {
            bool success = Product.DeleteProduct(this.ID);
            if (success)
                this.ID = 0;
            return success;
        }

        public int Insert()
        {
            return Product.InsertProduct(this.DepartmentID, this.Title, this.CodeProduct, this.Orgin, this.UnitPrice, this.Description,
                    this.DiscountPercentage, this.Quantity, this.IsShow, this.IsNew, this.PictureId);
        }

        public bool Update()
        {
            return Product.UpdateProduct(this.ID, this.DepartmentID, this.Title, this.CodeProduct, this.Orgin, this.UnitPrice, this.Description,
                    this.DiscountPercentage, this.Quantity, this.IsShow, this.IsNew, this.PictureId);
        }

        public bool Rate(int rating)
        {
            return Product.RateProduct(this.ID, rating);
        }

        public bool DecrementUnitsInStock(int quantity)
        {
            bool success = Product.DecrementProductUnitsInStock(this.ID, quantity);
            if (success)
                this.UnitsInStock -= quantity;
            return success;
        }

        public bool IncrementViewCount()
        {
            return Product.IncrementProductViewCount(this.ID);
        }
        #endregion


    }
}
